﻿"use strict";

const roomMgr = require("../roomMgr");
const clientMgr = require("../clientMgr");
const socket = require('../../base_net/socket');
const crypto = require('../../utils/crypto');
const logger = require("../../utils/logger");
const db = require("../../utils/db");
var utils = require("../../utils/utils");

var games = {};
var gameSeatsOfUsers = {};
//超过半小时自动解散
var  kickList = {};

const SPECIAL_CARD_TYPE = {
    SUPREME_DRAGON: 33,  // 至尊清龙
    DRAGON: 32,          // 一条龙
    TWELVE_ROYAL: 31,    // 十二皇族
    THREE_SAME_DECOR_STRAIGHT: 30,   // 三同花顺
    THREE_BOMB: 29,      // 三分天下
    ALL_BIG: 28,         // 全大
    ALL_SMALL: 27,       // 全小
    ALL_SAME_DECOR: 26,  // 凑一色
    DOUBLE_MONSTER_DASH_THREE: 25,       // 双怪冲三
    FOUR_LEOPARD: 24,       // 四套三对
    FIVE_PAIR_ONE_LEOPARD: 23,  // 五对三条
    SIX_PAIR: 22,           // 六对半
    THREE_STRAIGHT: 21,     // 三顺子
    THREE_SAME_DECOR: 20,   // 三同花
};

const COMMON_CARD_TYPE = {
    SAME_DECOR_STRAIGHT: 17,    // 同花顺
    BOMB: 16,           // 炸弹
    GOURD: 15,          // 葫芦
    SAME_DECOR: 14,     // 同花
    STRAIGHT: 13,       // 顺子
    LEOPARD: 12,        // 豹子
    TWO_PAIR: 11,       // 两对
    ONE_PAIR: 10,       // 一对
};

exports.setReady = function(userId,value){
    var roomId = roomMgr.getUserRoomId(userId);
    if(roomId == null){
        return;
    }
    var roomInfo = roomMgr.getRoom(roomId);
    if(roomInfo == null){
        return;
    }
    var seatIndex = roomMgr.getUserIndex(userId);
    if(seatIndex == null){
        return;
    }
    var s = roomInfo.seats[seatIndex];
    s.ready = value?true:false;
    clientMgr.broadcastInRoom(socket.resp.user_ready,{userId:userId,ready:value},userId,true);
    if((kickList[userId] || kickList[userId] >= 0) && s.sit == 1){
        delete kickList[userId];
    }

    var game = games[ roomId ];
    if( game == null ) {
        var count = 0;
        for( var i = 0; i < roomInfo.seats.length; ++i ) {
            var s = roomInfo.seats[ i ];
            if( s && s.userId > 0 && s.sit == 1){
                if(s.ready == false){
                    if(roomInfo.conf.maxGames > 0)return;
                    continue;
                }
                count ++;
            }
        }
        if(count <= 1)return;
        if(roomInfo.numOfGames == 0){
            roomMgr.setStart( roomId );
        }
        //人数已经到齐了，并且都准备好了，则开始新的一局
        logger.game_log("启动十三水游戏");
        begin( roomId );
    }
}

exports.gameBegin = function(roomInfo){
    var roomId = roomInfo.roomId;
    if(roomInfo.numOfGames == 0){
        roomMgr.setStart( roomId );
    }
    logger.game_log("启动十三水游戏");
    //人数已经到齐了，并且都准备好了，则开始新的一局
    var game = games[ roomId ];
    if( game == null ) {
        begin(roomId);
    }
}
exports.sitDown = function(userId,value){
    var roomId = roomMgr.getUserRoomId(userId);
    if(roomId == null){
        return;
    }
    var roomInfo = roomMgr.getRoom(roomId);
    if(roomInfo == null){
        return;
    }
    var seatIndex = roomMgr.getUserIndex(userId);
    if(seatIndex == null){
        return;
    }

    var s = roomInfo.seats[seatIndex];
    s.sit = value == false?0:1;
    // getNiuniu2(userId);
    clientMgr.broadcastInRoom(socket.resp.user_sit,{userId:userId,sit:s.sit},userId,true);

    if(roomInfo.numOfGames > 0 || roomInfo.conf.maxGames <= 0){
        delete kickList[userId];
    }
}
exports.syncInfo = function(userId){
    var roomId = roomMgr.getUserRoomId(userId);
    if(roomId == null){
        return;
    }
    var roomInfo = roomMgr.getRoom(roomId);
    if(roomInfo == null || roomInfo.numOfGames == 0){
        return;
    }

    var game = games[ roomId ];
    var data = {};
    if( game != null ) {
        var ddd = game.gameSeats[game.button];

        data = {
            state : game.state,
            gameState:roomInfo.gameState,
            button : ddd != null?ddd.userId:0,
        };
        data.seats = [];
        for(var i = 0; i < roomInfo.conf.roomNum; ++i) {
            var rs = roomInfo.seats[i];
            var sd = game.gameSeats[i];
            if( !sd ) continue;
            
            if(sd.userId == userId){
                rs.exitAfterEnd = false;
            }

            var s = {
                userId:sd.userId,
                useSpecialCard: sd.useSpecialCard,
                score1 : sd.score1,
                hasXia : sd.hasXia,
                score2 : sd.score2,
                hasLiang : sd.hasLiang,
                sit : sd.sit,
                ready : rs.ready,
            }

            var holds = null;
            if(data.state == 5){
                holds = sd.holds;
                var niu = calculate(holds);
                s.niu = niu;
            }
            else{
                if(sd.sit == 1 && sd.userId == userId){
                    if (sd.hasCombine) {
                        holds = utils.clone(sd.combineCards);
                    } else {
                        holds = utils.clone(sd.holds);
                    }
                }
            }
            s.holds = holds;
            data.seats.push(s);
        }
    }
    else{
        data = {
            state : 0,
            gameState:roomInfo.gameState,
        };
        data.seats = [];
        for(var i = 0; i < roomInfo.conf.roomNum; ++i) {
            var sd = roomInfo.seats[i];
            if( sd.userId <= 0 ) continue;

            var s = {
                userId:sd.userId,
                ready : sd.ready,
                sit : sd.sit,
            }
            data.seats.push(s);
        }
    }
    data.record = roomInfo.allRecord;
    //同步整个信息给客户端
    clientMgr.sendMsg(userId,socket.resp.game_sync,data);
}

exports.get_tick_time = function(userId) {
    var roomId = roomMgr.getUserRoomId(userId);
    if(roomId == null){
        return;
    }
    var roomInfo = roomMgr.getRoom(roomId);
    if(roomInfo == null){
        return null;
    }
    if(kickList[userId] == null || kickList[userId] <= 0) {
        var seatIndex = roomMgr.getUserIndex(userId);
        if (seatIndex == null || seatIndex == 0) {
            return kickList;
        }
        var s = roomInfo.seats[seatIndex];
        if (s.sit == 0 || (s.ready == 0 && roomInfo.conf.maxGames > 0)) {
            kickList[userId] = 120;
        }
        /*else if (s.ready == 0) {
            kickList[userId] = 120;
        }*/
    }
    return kickList;
}

exports.exitAfterEnd = function (roomInfo,seatIndex){
    // if(roomInfo.owner == "999999"){
        var game = games[ roomInfo.roomId ];
        if( game == null ) {
            return false;
        }
        else{
            roomInfo.seats[seatIndex].exitAfterEnd = true;
            return true;
        }
    // }
    return true;
}
function clearExit(roomInfo) {
    if (roomInfo == null) return;
    var roomId = roomInfo.roomId;
    for(var i = 0; i < roomInfo.seats.length; ++i) {
        var rs = roomInfo.seats[i];
        if(rs.exitAfterEnd) {// || clientMgr.isOnline(rs.userId) == false){
            if (rs.exitAfterEnd && roomMgr.isCreator(roomId, rs.userId)) {
                clientMgr.broadcastInRoom(socket.resp.dispress,"dispress",rs.userId,false);
                clientMgr.kickAllInRoom(roomId);
                roomMgr.destroy(roomId);
                return;
            }
            rs.exitAfterEnd = false;
            clientMgr.sendMsg(rs.userId,socket.resp.exit_result,rs.userId);
            //通知其它玩家，有人退出了房间
            clientMgr.broadcastInRoom(socket.resp.exit_notify,rs.userId,rs.userId,false);

            roomMgr.exitRoom(rs.userId);
        }
    }
}
//开始新的一局
function begin(roomId) {
    var state = {
        idle : 0,
        // qiangzhuang : 1,
        // dingzhuang : 2,
        // xiazhu : 3,
        // cuopai : 4,
        combine_card: 3,
        bipai : 5,
    };

    var roomInfo = roomMgr.getRoom(roomId);
    if(roomInfo == null || games[roomId] != null){
        return;
    }

    clearExit(roomInfo);

    var roomInfo = roomMgr.getRoom(roomId);
    if(roomInfo == null || games[roomId] != null){
        return;
    }

    roomMgr.payGameCost(roomId);

    var seats = roomInfo.seats;

    logger.game_log("房间信息", roomInfo.conf);
    var game = {
        conf:roomInfo.conf,
        roomInfo:roomInfo,
        allState : state,

        // qiangzhuangTime : 6,
        // dingzhuangTime : 5,
        xiazhuTime : 60,
        // cuopaiTime : 10,
        liangpaiTime  : 10,
        nextGameTime : 5,

        allCards : [],
        currentIndex:0,
        gameSeats:[],

        button: 0,
        state:0,

        actionList:[],
    };
    roomInfo.numOfGames++;
    db.update_numOfGames(roomId,roomInfo.numOfGames);

    for(var i = 0; i < game.conf.roomNum; ++i) {
        if(seats[i].userId <= 0)continue;
        var data = game.gameSeats[i] = {};
        data.game = game;		//循环引用
        data.seatIndex = i;

        data.sit = seats[i].sit;
        data.userId = seats[i].userId;
        //持有的牌
        data.holds = [];

        data.score = 0;
        //抢庄倍数
        // data.hasQiang = false;
        // data.score1 = 0;
        //下注倍数
        data.hasCombine = false;
        // data.hasXia = false;
        // data.scoreBetting = 0;
        // data.hasLiang = false;
        data.combineCards = [];
        data.useSpecialCard = false;
        data.shoot = [];
    }

    var allHolds = [];

    // 只有一个人就结束游戏
    var count = 0;
    for(var i = 0; i < seats.length; ++i) {
        if (!game.gameSeats[i]) continue;
        //开局时，通知前端必要的数据
        var s = seats[i];
        if(s.ready == 1){
            count += 1;
        }
    }
    logger.game_log("目前在坐的有", count, "人");
    if(count <= 1){
        if(roomInfo.owner != "999999"){
            // doGameOver2(game,roomId,true);
        }
        return;
    }

    roomInfo.gameState = "playing";
    clientMgr.broadcastInRoom2(socket.resp.game_state,{state:roomInfo.gameState},roomId);

    games[roomId] = game;
    //洗牌
    shuffle(game);
    //发牌
    deal(game);

    for(var i = 0; i < seats.length; ++i) {
        if (!game.gameSeats[i]) continue;
        //开局时，通知前端必要的数据
        var s = seats[i];
        //通知游戏开始
        clientMgr.sendMsg(s.userId, socket.resp.game_begin);
        //通知玩家手牌
        //var holds = utils.clone(game.gameSeats[i].holds);
        //holds[holds.length-1] = -1;
        //var data = {userId:s.userId,holds:holds};
        //clientMgr.sendMsg(s.userId, socket.resp.game_holds, [data]);
        allHolds.push({userId:s.userId,holds:game.gameSeats[i].holds,sit:s.sit});
        //通知还剩多少局
        clientMgr.sendMsg(s.userId, socket.resp.game_num, roomInfo.numOfGames);
        // 更新权限
        updatePermission(s.userId);
    }
    for(var i = 0; i < seats.length; ++i) {
        if (!game.gameSeats[i]) continue;
        var s = seats[i];
        var allHolds2 = utils.clone(allHolds);
        for(var j=0;j<allHolds2.length;j++){
            var holds = allHolds2[j].holds;
            if(s.sit == 1 && s.userId == allHolds2[j].userId){
                // holds[holds.length-1] = -1;
            }
            else{
                allHolds2[j].holds = null;
            }
        }
        clientMgr.sendMsg(s.userId, socket.resp.game_holds, allHolds2);
    }
    recordGameAction(game,socket.resp.game_begin);
    recordGameAction(game,socket.resp.game_holds,allHolds);
    recordGameAction(game,socket.resp.game_num,roomInfo.numOfGames);

    game.state = game.allState.combine_card;
    combineCard(game);

    // game.state = game.allState.qiangzhuang;
    // clientMgr.broadcastInRoom2(socket.resp.qiangzhuang_all,{time:game.qiangzhuangTime},game.roomInfo.roomId,true);
    // recordGameAction(game,socket.resp.qiangzhuang_all,{time:game.qiangzhuangTime});
    // setBanker(game);
    // game.timeId1 = setTimeout(function () {
    //     dingzhuang(game);
    // },game.qiangzhuangTime * 1000);
};

function combineCard(game) {
    for (var i = 0; i < game.gameSeats.length; ++i) {
        var seatData = game.gameSeats[i];
        if(!seatData || seatData.sit == 0) continue;
        if(seatData.userId > 0) {
            var cardType = getSpecialCardType(seatData.holds);
            clientMgr.sendMsg(seatData.userId, socket.resp.combine_card, {time:game.xiazhuTime,holdType:cardType});
        }
    }

    game.timeId1 = setTimeout(function () {
        bipai(game);
    },game.xiazhuTime * 1000);
}

// function betting(game) {
//     if (game.timerIdBetting != null) {
//         clearTimeout(game.timerIdBetting);
//     }
//     // if(game.timerIdBetting != null && game.timerIdBetting <= 0) return;

//     var userSeatIndex = game.turnGamber;
//     if (game.canOver) { // 头家反带操作结束
//         game.canOver = null;
//         // clearTimeout(game.timerIdBetting);
//         // game.timerIdBetting = -1;
//         bipai(game);
//         return;
//     }
    
//     var gambler = game.gameSeats[userSeatIndex];
//     if (game.button == userSeatIndex && game.timerIdBetting != null) { // 重新轮到头家
//         if (game.isReverseBelt && gambler.scoreBetting > 0) {  // 头家反带
//             var data = {time:game.xiazhuTime,gambler:gambler.userId,operates:DXOptionalOperate.BELT,fundPool:game.fundPool,beltCost:game.beltNowCost};
//             clientMgr.broadcastInRoom2(socket.resp.dx_turn_betting_notify,data,game.roomInfo.roomId,true);
//             // recordGameAction(game,socket.resp.dx_turn_betting_notify,{time:game.xiazhuTime,gambler:gambler.userId,operates:DXOptionalOperate.BELT});

//             game.timerIdBetting = setTimeout(function () {
//                 exports.xiazhu(game.gameSeats[game.button].userId, 0);
//             }, game.xiazhuTime * 1000);
//             game.canOver = true;
//         } else {
//             // clearTimeout(game.timerIdBetting);
//             // game.timerIdBetting = -1;
//             bipai(game);
//         }
//         return;
//     }
//     // clearTimeout(game.timerIdBetting);
//     // game.timerIdBetting = -1;

//     if(!gambler || gambler.sit == 0) {
//         logger.game_log("下注阶段有人跑路了");
//         return;
//     }

//     var op = null;
//     if (game.isOnlyEat) {
//         if (game.button == userSeatIndex) {
//             op = DXOptionalOperate.EAT;
//         } else {
//             op = DXOptionalOperate.BELT;
//         }
//     } else {
//         if (game.button == userSeatIndex) {
//             op = DXOptionalOperate.EAT_TOUCH;
//         } else {
//             op = DXOptionalOperate.EAT_TOUCH_BELT;
//         }
//     }
//     var data = {time:game.xiazhuTime,gambler:gambler.userId,operates:op,fundPool:game.fundPool,beltCost:game.beltNowCost};
//     clientMgr.broadcastInRoom2(socket.resp.dx_turn_betting_notify,data,game.roomInfo.roomId,true);
//     // recordGameAction(game,socket.resp.dx_turn_betting_notify,{time:game.xiazhuTime,gambler:gambler.userId,operates:op});

//     game.state = game.allState.xiazhu;

//     game.timerIdBetting = setTimeout(function () {
//         // game.turnGamber = getNextUserIndex(game, game.turnGamber);
//         // betting(game);
//         exports.xiazhu(gambler.userId, 0);
//     }, game.xiazhuTime * 1000);
// }

function bipai(game){
    if(game.timeId4 <= 0)return;
    game.timeId4 = -1;
    logger.game_log("下注完成，到亮牌阶段");

    for (var l=0;l<game.gameSeats.length;l++) {
        var gamber = game.gameSeats[l];
        if (!gamber) continue;
        var holds = gamber.holds;
        if (gamber.combineCards.length > 0) {
            holds = gamber.combineCards;
        }
        if (gamber.useSpecialCard) {
            gamber.cardType = getSpecialCardType(gamber.holds);
        } else {
            gamber.cardType = [];
            for (let j = 0; j < 3; j++) {
                gamber.cardType.push(getCommonCardType(gamber.combineCards[j]));
            }
        }
        clientMgr.broadcastInRoom(socket.resp.liangpai_notify, {userId: gamber.userId,holds:holds,sit:gamber.sit,cardType:gamber.cardType},gamber.userId,true);
        recordGameAction(game, socket.resp.liangpai_notify, {userId: gamber.userId,holds:holds,sit:gamber.sit,cardType:gamber.cardType});
        clientMgr.sendMsg(gamber.userId, socket.resp.bipai_all, {time:game.liangpaiTime});
    }

    game.state = game.allState.bipai;
    game.timeId5 = setTimeout(function () {
        var roomId = game.roomInfo.roomId;
        doGameOver2(game,roomId);
    },game.liangpaiTime * 1000);
}

exports.qiangzhuang = function (userId,value) {
    var roomId = roomMgr.getUserRoomId(userId);
    if(roomId == null){
        return;
    }
    var seatIndex = roomMgr.getUserIndex(userId);
    if(seatIndex == null){
        return;
    }
    var game = games[ roomId ];
    if( game == null ) {
        return;
    }
    if(game.state != game.allState.qiangzhuang)return;

    var gs = game.gameSeats[seatIndex];
    gs.score1 = value;
    gs.hasQiang = true;
    clientMgr.broadcastInRoom(socket.resp.qiangzhuang_notify,{userId:userId,value:value},userId,true);
    recordGameAction(game,socket.resp.qiangzhuang_notify,{userId:userId,value:value});

    var hasOver = true;
    for (var i=0;i<game.gameSeats.length;i++) {
        var ddd = game.gameSeats[i];
        if(!ddd || ddd.sit == 0)continue;
        if(ddd.hasQiang == false){
            hasOver = false;
        }
    }
    if(hasOver){
        dingzhuang(game);
    }
}

exports.useSpecialCard = function(userId) {
    var roomId = roomMgr.getUserRoomId(userId);
    if(roomId == null){
        return;
    }
    var roomInfo = roomMgr.getRoom(roomId);
    if(roomInfo == null){
        return;
    }
    var seatIndex = roomMgr.getUserIndex(userId);
    if(seatIndex == null){
        return;
    }
    var game = games[ roomId ];
    if( game == null ) {
        return;
    }
    if(game.state != game.allState.combine_card)return;

    var gamber = game.gameSeats[seatIndex];
    var type = getSpecialCardType(gamber.holds);
    if (type <= 0) return;

    gamber.useSpecialCard = true;
    var holds = getSortSpecialCard(gamber.holds, type);
    gamber.holds = [].concat.apply([], holds);
    clientMgr.sendMsg(userId, socket.resp.combine_card_result, {holds:holds});

    combineFinish(game, seatIndex);
}
function combineFinish(game, seatIndex) {
    game.gameSeats[seatIndex].hasCombine = true;
    for (var l=0;l<game.gameSeats.length;l++) {
        var gamber = game.gameSeats[l];
        if (!gamber) continue;
        if (!gamber.hasCombine) {
            return;
        }
    }
    bipai(game);
}
exports.combineCardFinish = function(userId, combineCards) {
    logger.game_log("用户组牌", userId, combineCards);
    var roomId = roomMgr.getUserRoomId(userId);
    if(roomId == null){
        return;
    }
    var roomInfo = roomMgr.getRoom(roomId);
    if(roomInfo == null){
        return;
    }
    var seatIndex = roomMgr.getUserIndex(userId);
    if(seatIndex == null){
        return;
    }
    var game = games[ roomId ];
    if( game == null ) {
        return;
    }
    if(game.state != game.allState.combine_card)return;
    var limit = [3, 5, 5];
    for (var i = 0; i < combineCards.length; ++i) {
        if (combineCards[i].length != limit[i]) {
            clientMgr.sendMsg(userId, socket.resp.combine_card_result, {error:1});
            return;
        }
    }
    if (isPourWater(combineCards)) {
        logger.game_log("玩家", userId, "倒水");
        clientMgr.sendMsg(userId, socket.resp.combine_card_result, {error:2});
        return;
    }
    game.gameSeats[seatIndex].holds = [].concat.apply([], combineCards);
    game.gameSeats[seatIndex].combineCards = combineCards;
    clientMgr.sendMsg(userId, socket.resp.combine_card_result, {holds:combineCards});
    combineFinish(game, seatIndex);
}

exports.kanpai = function (userId) {
    var roomId = roomMgr.getUserRoomId(userId);
    if(roomId == null){
        return;
    }
    var seatIndex = roomMgr.getUserIndex(userId);
    if(seatIndex == null){
        return;
    }
    var game = games[ roomId ];
    if( game == null ) {
        return;
    }
    if(game.state != game.allState.cuopai)return;

    clientMgr.broadcastInRoom(socket.resp.kanpai_notify,{userId:userId},userId,true);
    recordGameAction(game,socket.resp.kanpai_notify,{userId:userId});
}
exports.liangpai = function (userId) {
    var roomId = roomMgr.getUserRoomId(userId);
    if(roomId == null){
        return;
    }
    var seatIndex = roomMgr.getUserIndex(userId);
    if(seatIndex == null){
        return;
    }
    var game = games[ roomId ];
    if( game == null ) {
        return;
    }
    if(game.state != game.allState.cuopai)return;

    var gs = game.gameSeats[seatIndex];
    if(gs.hasLiang)return;
    gs.hasLiang = true;

    var niu = calculate(gs.holds);
    clientMgr.broadcastInRoom(socket.resp.liangpai_notify,{userId:userId,holds: gs.holds,niu:niu,sit:gs.sit},userId,true);
    recordGameAction(game,socket.resp.liangpai_notify,{userId:userId,holds: gs.holds,niu:niu,sit:gs.sit});

    var hasOver = true;
    for (var i=0;i<game.gameSeats.length;i++) {
        var ddd = game.gameSeats[i];
        if(!ddd || ddd.sit == 0)continue;
        if(ddd.hasLiang == false){
            hasOver = false;
        }
    }
    if(hasOver){
        bipai(game,userId);
    }
}
function shuffle( game ) {
    let allCards = game.allCards;
    //初始化牌组
    for( let i = 1; i <= 13; i ++ ){
        for( let j = 1; j <= 4; j ++ ) {
            allCards.push("" + i + j);
        }
    }

    //数组重新排序
	for( let i = 0; i < allCards.length; ++i ) {
		let lastIndex = allCards.length - 1 - i;
		let index = Math.floor( Math.random() * lastIndex );
		let t = allCards[ index ];
        allCards[ index ] = allCards[ lastIndex ];
        allCards[ lastIndex ] = t;
	}
}
function deal(game){
    //强制清0
    game.currentIndex = 0;

    var seatIndex = 0;
    for(var i = 0; i < 13 * game.gameSeats.length; ++i){
        if(game.gameSeats[seatIndex] == null){
            seatIndex ++;
            seatIndex %= game.gameSeats.length;
            continue;
        }
        var holds = game.gameSeats[seatIndex].holds;
        if(holds == null){
            holds = [];
            game.gameSeats[seatIndex].holds = holds;
        }
        mopai(game,seatIndex);
        seatIndex ++;
        seatIndex %= game.gameSeats.length;
    }
    for(var i = 0; i < game.gameSeats.length; ++i){
        if(game.gameSeats[i] == null){
            continue;
        }
        var holds = game.gameSeats[i].holds;
        game.gameSeats[i].holds = holds.sort(function(a, b) {
            // var decorA = getCardDecor(a);
            // var decorB = getCardDecor(b);
            // if (decorA != decorB) {
            //     return decorA - decorB;
            // }
            var valueA = getCardPoint(a);
            var valueB = getCardPoint(b);
            return valueA - valueB;
        });
        logger.game_log(game.gameSeats[i].userId + " 摸到的牌为: " + holds);
    }
}
function mopai( game, seatIndex ) {
    if(game.currentIndex == game.allCards.length){
        return -1;
    }
    var data = game.gameSeats[seatIndex];
    var holds = data.holds;
    var pai = game.allCards[game.currentIndex];
    game.currentIndex ++;
    holds.push( pai );
    return pai;
}


var CardDecor = {
    HEART: 2,   // 红桃
    BLOCK: 4,   // 方块
    SPADE: 1,   // 黑桃
    PLUM: 3,    // 梅花
}
// 获取花色
function getCardDecor(card) {
    return card % 10;
}

// 获取牌的值
function getCardValue(card) {
    return Math.floor(card / 10);
}

// 获取牌的点数
function getCardPoint(card) {
    var value = getCardValue(card);
    return value == 1 ? 14 : value;
}

// 至尊清龙
function isSupremeDragon(cards) {
    var decor = getCardDecor(cards[0]);
    var dict = {};
    for (var i = 0; i < cards.length; ++i) {
        var value = getCardValue(cards[i]);
        
        if (dict[value]) {
            return false;
        }
        if (decor != getCardDecor(cards[i])) {
            return false;
        }
        dict[value] = 1;
    }
    return true;
}

// 一条龙
function isDragon(cards) {
    var dict = {};
    for (var i = 0; i < cards.length; ++i) {
        var value = getCardValue(cards[i]);
        if (dict[value]) {
            return false;
        }
        dict[value] = 1;
    }
    return true;
}

// 十二皇族
function isTwelveRoyal(cards) {
    var small = 0;
    for (var i = 0; i < cards.length; ++i) {
        var value = getCardPoint(cards[i]);
        if (value <= 10) {
            small++;
            if (small > 1) {
                return false;
            }
        }
    }
    return true;
}

// 三同花顺
function isThreeSameDecorStraight(cards) {
    var dict = [];
    for (var i = 0; i < cards.length; ++i) {
        var value = getCardPoint(cards[i]);
        var decor = getCardDecor(cards[i]);
        var key = decor * 100 + value;
        dict[key] = dict[key] ? (dict[key] + 1) : 1;
    }
    var cnt = 0;
    var amount = 0;
    for (var decor = 1; decor <= 4; ++decor) {
        var cnt = 0;
        for (var value = 2; value <= 14; ++value) {
            var key = decor * 100 + value;
            if (dict[key]) {
                cnt++;
            } else {
                if (cnt > 0) {
                    if (cnt != 3 || cnt != 5 || cnt != 8 || cnt != 10) {
                        return false;
                    } else {
                        amount++;
                    }
                }
                cnt = 0;
            }
        }
        if (cnt > 0) {
            if (cnt != 3 || cnt != 5 || cnt != 8 || cnt != 10) {
                return false;
            } else {
                amount++;
            }
        }
    }
    if (amount > 3) {
        return false;
    }
    return true;
}
// 杂顺子
function isThreeStraight(cards) {
    var dict = [];
    for (var i = 0; i < cards.length; ++i) {
        var value = getCardValue(cards[i]);
        dict[value] = dict[value] ? (dict[value] + 1) : 1;
    }
    var cnt = 0;
    var begin = [];
    var end = [];
    for (var i = 2; i <= 14; ++i) {
        var value = i > 13 ? (i - 13) : i;
        if (dict[value]) {
            cnt++;
            if (dict[value-1]) {
                if (dict[i-1] < dict[value]) {
                    for (var j = 0; j < dict[value] - dict[i-1]; ++j) {
                        begin.push(value);
                    }
                } else if (dict[i-1] > dict[value]) {
                    for (var j = 0; j < dict[i-1] - dict[value]; ++j) {
                        end.push(value-1);
                    }
                }
            } else {
                begin.push(value);
            }
        } else {
            if (cnt > 0) {
                end.push(i-1);
            }
            cnt = 0;
        }
    }
    if (cnt > 0) {
        end.push(i-1);
    }
    if (begin.length > 3) {
        return false;
    }
    if (begin.length == 1) {
        return true;
    }
    if (begin.length == 2) {
        for (var i = 0; i < end.length; ++i) {
            var len = end[i] - begin[0] + 1;
            if (len == 3 || len == 5 || len == 8 || len == 10) {
                return true;
            }
        }
        return false;
    }

    var markBegin = [];
    var selectBegin = [];
    function check(times) {
        if (times == 3) {
            for (var i = 0; i < end.length; ++i) {
                var dist = end[i] - selectBegin[i] + 1;
                if (dist != 3 && dist != 5) {
                    return false;
                }
            }
            return true;
        }
        for (var i = 0; i < begin.length; ++i) {
            if (markBegin[i]) {
                continue;
            }
            if (begin[i] > end[times]) {
                return false;
            }
            markBegin[i] = true;
            selectBegin.push(begin[i]);
            if (check(times + 1)) {
                return true;
            }
            selectBegin.pop();
            markBegin[i] = false;
        }
        return false;
    }
    return check(0);
}

function getThreeStraight(cards) {
    var mark = [];
    var dict = [];
    for (var i = 0; i < cards.length; ++i) {
        let point = getCardPoint(cards[i]);
        dict[point] = dict[point] ? (dict[point] + 1) : 1;

        if (!mark[point]) mark[point] = [];
        mark[point].push(cards[i]);
    }
    // 方便三同花顺凑成对应的列表
    for (let point = 2; point <= 14; ++point) {
        mark[point].sort((a, b) => {
            return getCardDecor(a) - getCardDecor(b);
        });
    }

    var cnt = 0;
    var begin = [];
    var end = [];
    for (var i = 2; i <= 14; ++i) {
        var value = i;
        if (dict[value]) {
            cnt++;
            if (dict[value-1]) {
                if (dict[i-1] < dict[value]) {
                    for (var j = 0; j < dict[value] - dict[i-1]; ++j) {
                        begin.push(value);
                    }
                } else if (dict[i-1] > dict[value]) {
                    for (var j = 0; j < dict[i-1] - dict[value]; ++j) {
                        end.push(value-1);
                    }
                }
            } else {
                begin.push(value);
            }
        } else {
            if (cnt > 0) {
                end.push(i-1);
            }
            cnt = 0;
        }
    }
    if (cnt > 0) {
        end.push(i-1);
    }
    if (begin.length > 3) {
        return [];
    }
    var holds = [[], [], []];
    var pushCardToHold = function(card) {
        if (holds[0].length < 3) {
            holds[0].push(card);
        } else if (holds[1].length < 5) {
            holds[1].push(card);
        } else {
            holds[2].push(card);   
        }
    }
    var pushCard = function(b, e) {
        for (let value = b; value <= e; value++) {
            pushCardToHold(mark[value][0]);
            mark[value].splice(0, 0);
        }
    }
    if (begin.length == 1) {
        pushCard(begin[0], end[0]);
        return holds;
    }
    if (begin.length == 2) {
        for (var i = 0; i < end.length; ++i) {
            var len = end[i] - begin[0] + 1;
            if (len == 3 || len == 8) {
                pushCard(begin[0], end[i]);
                pushCard(begin[1], end[1-i]);
                break;
            } else if (len == 5 || len == 10) {
                pushCard(begin[1], end[1-i]);
                pushCard(begin[0], end[i]);
                break;
            }
        }
        return holds;
    }

    var markBegin = [];
    var selectBegin = [];
    function check(times) {
        if (times == 3) {
            for (var i = 0; i < end.length; ++i) {
                var dist = end[i] - selectBegin[i] + 1;
                if (dist != 3 && dist != 5) {
                    return false;
                }
            }
            
            for (var i = 0; i < end.length; ++i) {
                var dist = end[i] - selectBegin[i] + 1;
                if (dist == 3) {
                    pushCard(selectBegin[i], end[i]);
                    for (var j = 0; j < end.length; ++j) {
                        if (j == i) continue;
                        pushCard(selectBegin[j], end[j]);
                    }
                    return true;
                }
            }
        }
        for (var i = 0; i < begin.length; ++i) {
            if (markBegin[i]) {
                continue;
            }
            if (begin[i] > end[times]) {
                return false;
            }
            markBegin[i] = true;
            selectBegin.push(begin[i]);
            if (check(times + 1)) {
                return true;
            }
            selectBegin.pop();
            markBegin[i] = false;
        }
        return false;
    }
    check(0);
    return holds;
}

// 三分天下
function isThreeBomb(cards) {
    var dict = [];
    for (var i = 0; i < cards.length; ++i) {
        var value = getCardValue(cards[i]);
        dict[value] = dict[value] ? (dict[value] + 1) : 1;
    }
    var cnt = 0;
    for (var i = 1; i <= 13; ++i) {
        if (dict[i] && dict[i] >= 4) {
            cnt++;
        }
    }
    return cnt >= 3;
}

// 全大
function isAllBig(cards) {
    for (var i = 0; i < cards.length; ++i) {
        var value = getCardPoint(cards[i]);
        if (value < 8) {
            return false;
        }
    }
    return true;
}

// 全小
function isAllSmall(cards) {
    for (var i = 0; i < cards.length; ++i) {
        var value = getCardPoint(cards[i]);
        if (value > 8) {
            return false;
        }
    }
    return true;
}

// 凑一色
function isAllSameDecor(cards) {
    var decor = getCardDecor(cards[0]);
    for (var i = 0; i < cards.length; ++i) {
        if (decor != getCardDecor(cards[i])) {
            return false;
        }
    }
    return true;
}

function getSameCardValueCnt(cards) {
    var dict = [];
    for (var i = 0; i < cards.length; ++i) {
        var value = getCardValue(cards[i]);
        dict[value] = dict[value] ? (dict[value] + 1) : 1;
    }
    var cnt = [];
    for (var i = 1; i <= 13; ++i) {
        if (dict[i]) {
            cnt[dict[i]] = cnt[dict[i]] ? (cnt[dict[i]] + 1) : 1;
        }
    }
    return cnt;
}

// 双怪冲三
function isDoubleMonsterDashThree(cards) {
    var cnt = getSameCardValueCnt(cards);
    if (cnt[3] == 2 && cnt[2] == 3) {
        return true;
    }
    return false;
}

// 四套三条
function isFourLeopard(cards) {
    var cnt = getSameCardValueCnt(cards);
    if (cnt[3] == 4) {
        return true;
    }
    return false;
}

// 五对三条
function isFivePairOneLeopard(cards) {
    var cnt = getSameCardValueCnt(cards);
    if (cnt[3] == 1 && cnt[2] == 5) {
        return true;
    }
    return false;
}

// 六对半
function isSixPair(cards) {
    var cnt = getSameCardValueCnt(cards);
    if (cnt[2] == 6) {
        return true;
    }
    return false;
}

// 三同花
function isThreeSameDecor(cards) {
    var cnt = [];
    for (var i = 0; i < cards.length; ++i) {
        var decor = getCardDecor(cards[i]);
        cnt[decor] = cnt[decor] ? (cnt[decor] + 1) : 1;
    }
    var hasThree = false;
    for (var i = 0; i < cards.length; ++i) {
        if (cnt[i]) {
            if (cnt[i] != 3 && cnt[i] != 5 && cnt[i] != 8 && cnt[i] != 10) {
                return false;
            }
            if(cnt[i] == 3 || cnt[i] == 8) {
                if (hasThree) {
                    return false;
                }
                hasThree = true;
            }
        }
    }
    return true;
}

function getSpecialMultiple(cards) {
    if (isSupremeDragon(cards)) {
        return 52;
    } else if (isDragon(cards)) {
        return 26;
    } else if (isTwelveRoyal(cards)) {
        return 24;
    } else if (isThreeSameDecorStraight(cards)) {
        return 18;
    } else if (isThreeBomb(cards)) {
        return 16;
    } else if (isAllBig(cards) || isAllSmall(cards)) {
        return 12;
    } else if (isAllSameDecor(cards)) {
        return 10;
    } else if (isDoubleMonsterDashThree(cards)) {
        return 8;
    } else if (isFourLeopard(cards)) {
        return 8;
    } else if (isSixPair(cards) || isThreeStraight(cards) || isThreeSameDecor(cards)) {
        return 3;
    }
    return 1;
}

function getSpecialCardValue(cards) {
    if (isSupremeDragon(cards)) {
        return 103000000;
    } else if (isDragon(cards)) {
        return 102000000;
    } else if (isTwelveRoyal(cards)) {
        return 101000000;
    } else if (isThreeSameDecorStraight(cards)) {
        return 100000000;
    } else if (isThreeBomb(cards)) {
        return 99000000;
    } else if (isAllBig(cards)) {
        return 98000000;
    } else if (isAllSmall(cards)) {
        return 97000000;
    } else if (isAllSameDecor(cards)) {
        return 96000000;
    } else if (isDoubleMonsterDashThree(cards)) {
        return 95000000;
    } else if (isFourLeopard(cards)) {
        return 94000000;
    } else if (isFivePairOneLeopard(cards)) {
        return 93000000;
    } else if (isSixPair(cards)) {
        return 92000000;
    } else if (isThreeStraight(cards)) {
        return 91000000;
    } else if (isThreeSameDecor(cards)) {
        return 90000000;
    }
}

function compareSpecialCard(cards1, cards2) {
    var value1 = getSpecialCardValue(cards1);
    var value2 = getSpecialCardValue(cards2);
    if (value1 != value2) {
        return value1 - value2;
    }
    
    function getCardPointDict(cards) {
        var dict = {};
        for (var i = 0; i < cards.length; ++i) {
            var value = getCardPoint(cards[i]);
            dict[value] = dict[value] ? dict[value] + 1 : 1;
        }
        var amount = [];
        for (var value in dict) {
            if (!amount[dict[value]]) {
                amount[dict[value]] = [];
            }
            amount[dict[value]].push(value);
        }
        return amount;
    }

    var amount1 = getCardPointDict(cards1);
    var amount2 = getCardPointDict(cards2);

    for (var i = 4; i > 0; --i) {
        for (var j = 14; j > 1; --j) {
            var index1 = amount1[i] ? amount1[i].indexOf("" + j) : -1;
            var index2 = amount2[i] ? amount2[i].indexOf("" + j) : -1;
            if (index1 >= 0 && index2 >= 0) continue;
            if (index1 < 0 && index2 < 0) continue;
            return index1 - index2;
        }
    }
    return 0;
}

function getSortSpecialCard(holds, type) {
    var cards = [];

    if (type == SPECIAL_CARD_TYPE.THREE_SAME_DECOR_STRAIGHT) {
        cards = getThreeStraight(holds);
    } else if (type == SPECIAL_CARD_TYPE.THREE_STRAIGHT) {
        cards = getThreeStraight(holds);
    } else {
        for (var i = 0; i < holds.length; ++i) {
            cards[i] = parseInt(holds[i]);
        }
        if (type == SPECIAL_CARD_TYPE.THREE_SAME_DECOR) {
            cards.sort(function(a, b) {
                let decorA = getCardDecor(a);
                let decorB = getCardDecor(b);
                if (decorA != decorB) {
                    return decorA - decorB;
                } else {
                    return getCardPoint(a) - getCardPoint(b);
                }
            });
        } else {
            cards = cards.sort(function(a, b) {
                let pointA = getCardPoint(a);
                let pointB = getCardPoint(b);
                if (pointA != pointB) {
                    return pointA - pointB;
                } else {
                    return getCardDecor(a) - getCardDecor(b);
                }
            });
        }
        for (var i = 0; i < cards.length; ++i) {
            cards[i] = "" + cards[i];
        }
    }

    return cards;
}

function getSpecialCardType(cards) {
    if (isSupremeDragon(cards)) {
        return SPECIAL_CARD_TYPE.SUPREME_DRAGON;
    } else if (isDragon(cards)) {
        return SPECIAL_CARD_TYPE.DRAGON;
    } else if (isTwelveRoyal(cards)) {
        return SPECIAL_CARD_TYPE.TWELVE_ROYAL;
    } else if (isThreeSameDecorStraight(cards)) {
        return SPECIAL_CARD_TYPE.THREE_SAME_DECOR_STRAIGHT;
    } else if (isThreeBomb(cards)) {
        return SPECIAL_CARD_TYPE.THREE_BOMB;
    } else if (isAllBig(cards)) {
        return SPECIAL_CARD_TYPE.ALL_BIG;
    } else if (isAllSmall(cards)) {
        return SPECIAL_CARD_TYPE.ALL_SMALL;
    } else if (isAllSameDecor(cards)) {
        return SPECIAL_CARD_TYPE.ALL_SAME_DECOR;
    } else if (isDoubleMonsterDashThree(cards)) {
        return SPECIAL_CARD_TYPE.DOUBLE_MONSTER_DASH_THREE;
    } else if (isFourLeopard(cards)) {
        return SPECIAL_CARD_TYPE.FOUR_LEOPARD;
    } else if (isFivePairOneLeopard(cards)) {
        return SPECIAL_CARD_TYPE.FIVE_PAIR_ONE_LEOPARD;
    } else if (isSixPair(cards)) {
        return SPECIAL_CARD_TYPE.SIX_PAIR;
    } else if (isThreeStraight(cards)) {
        return SPECIAL_CARD_TYPE.THREE_STRAIGHT;
    } else if (isThreeSameDecor(cards)) {
        return SPECIAL_CARD_TYPE.THREE_SAME_DECOR;
    }
    return 0;
}

// 普通牌型同花顺
function isCommonSameDecorStraight(cards) {
    if (!isCommonSameDecor(cards)) {
        return false;
    }
    if (!isCommonStraight(cards)) {
        return false;
    }
    return true;
}

// 普通牌型铁支
function isCommonBomb(cards) {
    var dict = {};
    for (var i = 0; i < cards.length; ++i) {
        var value = getCardValue(cards[i]);
        dict[value] = dict[value] ? (dict[value] + 1) : 1;
    }
    for (var i in dict) {
        if (dict[i] == 4) {
            return true;
        }
    }
    return false;
}

// 普通牌型葫芦
function isCommonGourd(cards) {
    var dict = {};
    for (var i = 0; i < cards.length; ++i) {
        var value = getCardValue(cards[i]);
        dict[value] = dict[value] ? (dict[value] + 1) : 1;
    }
    var cnt = [];
    for (var i in dict) {
        cnt[dict[i]] = cnt[dict[i]] ? (cnt[dict[i]] + 1) : 1;
    }
    if (cnt[2] >= 1 && cnt[3] >= 1) {
        return true;
    }
    return false;
}

// 普通牌型同花
function isCommonSameDecor(cards) {
    var decor;
    for (var i = 0; i < cards.length; i++) {
        var type = getCardDecor(cards[i]);
        if(decor == null){
            decor = type;
        }
        else if(type != decor){
            return false;
        }
    }
    return true;
}

// 普通牌型顺子
function isCommonStraight(cards) {
    var dict = {};
    var minValue = 99;
    var maxValue = 0;
    for (var i = 0; i < cards.length; i++) {
        var value = getCardPoint(cards[i]);
        if (value < minValue) {
            minValue = value;
        }
        if (value > maxValue) {
            maxValue = value;
        }
        if (dict[value]) {  // 有对子或者豹子，肯定不是顺子
            return false;
        }
        dict[value] = 1;
    }
    
    if ((maxValue - minValue + 1) == cards.length) {
        return true;
    }
    return false;
}

// 普通牌型三条
function isCommonLeopard(cards) {
    var dict = {};
    for (var i = 0; i < cards.length; ++i) {
        var value = getCardValue(cards[i]);
        dict[value] = dict[value] ? (dict[value] + 1) : 1;
    }
    var cnt = [];
    for (var i in dict) {
        cnt[dict[i]] = cnt[dict[i]] ? (cnt[dict[i]] + 1) : 1;
    }
    if (cnt[3] >= 1) {
        return true;
    }
    return false;
}

// 普通牌型两对
function isCommonTwoPair(cards) {
    var dict = {};
    for (var i = 0; i < cards.length; ++i) {
        var value = getCardValue(cards[i]);
        dict[value] = dict[value] ? (dict[value] + 1) : 1;
    }
    var cnt = [];
    for (var i in dict) {
        cnt[dict[i]] = cnt[dict[i]] ? (cnt[dict[i]] + 1) : 1;
    }
    if (cnt[2] >= 2) {
        return true;
    }
    return false;
}

// 普通牌型一对
function isCommonOnePair(cards) {
    var dict = {};
    for (var i = 0; i < cards.length; ++i) {
        var value = getCardValue(cards[i]);
        dict[value] = dict[value] ? (dict[value] + 1) : 1;
    }
    var cnt = [];
    for (var i in dict) {
        cnt[dict[i]] = cnt[dict[i]] ? (cnt[dict[i]] + 1) : 1;
    }
    if (cnt[2] >= 1) {
        return true;
    }
    return false;
}

function getMixCardPoint(cards) {
    if (!cards) return 0;
    var dict = {};
    for (var i = 0; i < cards.length; ++i) {
        var value = getCardPoint(cards[i]);
        dict[value] = dict[value] ? dict[value] + 1 : 1;
    }

    var point = 0;
    for (var i = 2; i <= 14; ++i) {
        while (dict[i] && dict[i] > 0) {
            --dict[i];
            point = point * 20 + i;
        }
    }
    return point;
}

function getPairCardPoint(cards) {
    if (!cards) return 0;
    var dict = {};
    for (var i = 0; i < cards.length; ++i) {
        var value = getCardPoint(cards[i]);
        dict[value] = dict[value] ? dict[value] + 1 : 1;
    }

    var amount = [];
    for (var value in dict) {
        if (!amount[dict[value]]) {
            amount[dict[value]] = [];
        }
        amount[dict[value]].push(value);
    }

    var point = 0;
    for (var i = 1; i <= 4; ++i) {
        for (var j = 2; j <= 14; ++j) {
            if (!amount[i]) continue;
            if (amount[i].indexOf("" + j) < 0) continue;
            for (var k = 0; k < i; ++k) {
                point = point * 20 + i;
            }
        }
    }
    return point;
}

function getCommonSpecialValue(cards) {
    // getMixCardPoint的值不会超过20的5次方
    if (!cards) {
        return 0;
    }
    if (isCommonSameDecorStraight(cards)) {
        return 80000000 + getMixCardPoint(cards);
    } else if (isCommonBomb(cards)) {
        return 70000000 + getPairCardPoint(cards);
    } else if (isCommonGourd(cards)) {
        return 60000000 + getPairCardPoint(cards);
    } else if (isCommonSameDecor(cards)) {
        return 50000000 + getMixCardPoint(cards);
    } else if (isCommonStraight(cards)) {
        return 40000000 + getMixCardPoint(cards);
    } else if (isCommonLeopard(cards)) {
        return 30000000 + getPairCardPoint(cards);
    } else if (isCommonTwoPair(cards)) {
        return 20000000 + getPairCardPoint(cards);
    } else if (isCommonOnePair(cards)) {
        return 10000000 + getPairCardPoint(cards);
    } else {
        return getMixCardPoint(cards);
    }
}

function getCommonCardType(cards) {
    if (!cards) {
        return 0;
    }
    if (isCommonSameDecorStraight(cards)) {
        return COMMON_CARD_TYPE.SAME_DECOR_STRAIGHT;
    } else if (isCommonBomb(cards)) {
        return COMMON_CARD_TYPE.BOMB;
    } else if (isCommonGourd(cards)) {
        return COMMON_CARD_TYPE.GOURD;
    } else if (isCommonSameDecor(cards)) {
        return COMMON_CARD_TYPE.SAME_DECOR;
    } else if (isCommonStraight(cards)) {
        return COMMON_CARD_TYPE.STRAIGHT;
    } else if (isCommonLeopard(cards)) {
        return COMMON_CARD_TYPE.LEOPARD;
    } else if (isCommonTwoPair(cards)) {
        return COMMON_CARD_TYPE.TWO_PAIR;
    } else if (isCommonOnePair(cards)) {
        return COMMON_CARD_TYPE.ONE_PAIR;
    } else {
        return getMixCardPoint(cards);
    }
}

function getCommonMultiple(pierNum, cards) {
    if (isCommonSameDecorStraight(cards)) {
        if (pierNum == 1) {
            return 10;
        } else if (pierNum == 2) {
            return 5;
        }
    } else if (isCommonBomb(cards)) {
        if (pierNum == 1) {
            return 8;
        } else if (pierNum == 2) {
            return 4;
        }
    } else if (isCommonLeopard(cards)) {// && getCardValue(cards[0]) == 1) {
        if (pierNum == 0) {
            return 3;
        }
    } else if (isCommonGourd(cards)) {
        if (pierNum == 1) {
            return 2;
        }
    }
    return 1;
}

// 是否倒水
function isPourWater(cards) {
    var lastValue = 0;
    let values = [];
    for (var i = 0; i < cards.length; ++i) {
        var value = getCommonSpecialValue(cards[i]);
        if (i == 0) {
            value = (value % 10000000) * 400 + Math.floor(value / 10000000) * 10000000;
        }
        values.push(value);
        if (value < lastValue) {
            logger.game_log("倒水", cards, values);
            return true;
        }
        lastValue = value;
    }
    return false;
}

function calculate(holds) {

}

function calculateResult(game,roomInfo){
    var kill = [];
    // 先普通比牌

    function addKill(s, t, score) {
        if (!kill[s]) {
            kill[s] = [];
        }
        kill[s][t] = score;
    }
    
    for (var i = 0; i < game.gameSeats.length; ++i) {
        var gamber = game.gameSeats[i];
        if (gamber == null || gamber.sit == 0) continue;
        if (gamber.useSpecialCard) continue;

        var win1 = 0;
        var win2 = 0;
        var winPoint = 0;
        var difen = game.conf.difen;
        for (var j = i + 1; j < game.gameSeats.length; ++j) {
            var gamber2 = game.gameSeats[j];
            if (gamber2 == null || gamber2.sit == 0) continue;
            if (gamber2.useSpecialCard) continue;
            
            for (var k = 0; k < 3; ++k) {
                var value1 = getCommonSpecialValue(gamber.combineCards[k]);
                var value2 = getCommonSpecialValue(gamber2.combineCards[k]);
                if (value1 > value2) {
                    var point = getCommonMultiple(k, gamber.combineCards[k]) * difen;
                    gamber.score += point;
                    gamber2.score -= point;
                    win1++;
                    winPoint += point;
                } else if (value1 < value2) {
                    var point = getCommonMultiple(k, gamber2.combineCards[k]) * difen;
                    gamber2.score += point;
                    gamber.score -= point;
                    win2++;
                    winPoint += point;
                }
            }
            
            // 打枪翻倍
            if (win1 == 0 && win2 > 0) {    // 被打枪或者碾过
                gamber2.shoot.push(i);
                gamber2.score += winPoint;
                gamber.score -= winPoint;
                addKill(j, i, winPoint * 2);
            }
            if (win2 == 0 && win1 > 0) {
                gamber.shoot.push(j);
                gamber.score += winPoint;
                gamber2.score -= winPoint;
                addKill(i, j, winPoint * 2);
            }
        }
    }

    // 再特殊比牌
    for (var i = 0; i < game.gameSeats.length; ++i) {
        var gamber = game.gameSeats[i];
        if (gamber == null || gamber.sit == 0) continue;
        if (!gamber.useSpecialCard) continue;

        var point = getSpecialMultiple(gamber.holds) * difen;
        for (var j = i + 1; j < game.gameSeats.length; ++j) {
            var gamber2 = game.gameSeats[j];
            if (gamber2 == null || gamber2.sit == 0) continue;

            if (gamber2.useSpecialCard) {
                var result = compareSpecialCard(gamber.holds, gamber2.holds);
                if (result > 0) {
                    gamber.score += point;
                    gamber2.score -= point;
                    addKill(i, j, point);
                } else if (result < 0) {
                    var point2 = getSpecialMultiple(gamber2.holds) * difen;
                    gamber2.score += point2;
                    gamber.score -= point;
                    addKill(j, i, point);

                }
            } else {
                gamber.score += point;
                gamber2.score -= point;
                addKill(i, j, point);
            }
        }
    }

    // 计算通杀
    for (var i = 0; i < game.gameSeats.length; ++i) {
        var gamber = game.gameSeats[i];
        if (gamber == null || gamber.sit == 0) continue;

        var hasKill = true;
        for (var j = 0; j < game.gameSeats.length; ++j) {
            if (i == j) continue;
            var gamber2 = game.gameSeats[j];
            if (gamber2 == null || gamber2.sit == 0) continue;

            if (!kill[i] || !kill[i][j]) {
                hasKill = false;
            }
        }
        if (hasKill) {
            for (var j = 0; j < game.gameSeats.length; ++j) {
                if (i == j) continue;
                var gamber2 = game.gameSeats[j];
                if (gamber2 == null || gamber2.sit == 0) continue;
                gamber.score += kill[i][j];
                gamber2.score -= kill[i][j];
            }
        }
    }
}

function doGameOver(game,userId,forceEnd){
    var roomId = roomMgr.getUserRoomId(userId);
    doGameOver2(game,roomId,forceEnd);
}
function doGameOver2(game,roomId,forceEnd){
	if(roomId == null){
		return;
	}
	var roomInfo = roomMgr.getRoom(roomId);
	if(roomInfo == null){
		return;
	}
	roomInfo.gameState = "idle";
    clientMgr.broadcastInRoom2(socket.resp.game_state,{state:roomInfo.gameState},roomId);

	var results = [];
    var dbusers = [];
	var dbresult = [];
    var backcount = 0,renshu = 0;
    var isEnd = false;
    var endInfo = null;

	if(game != null){
	    if(!forceEnd){
			calculateResult(game,roomInfo);	
		}

        if(roomInfo.allRecord == null){
	        roomInfo.allRecord = [];
            roomInfo.allRecord[0] = {};
        }
        roomInfo.fundPool = game.fundPool;

        var record;
        if(roomInfo.conf.maxGames > 0){
            record = roomInfo.allRecord[roomInfo.numOfGames] = {};
        }
        else{
            record = roomInfo.allRecord = {};
        }
        var endTime = Date.now();
        var cost_coins = function (data,rs) {
            db.rate_coins(data,function (info) {
                var difen = game.conf.difen;
                logger.game_log(rs.userId, "目前金币为", info.coins, "目前底分为", difen);
                // if(info.coins <= difen * 200){
                //     rs.sit = 0;
                //     exports.sitDown(rs.userId,false);
                // }
                data.coins = info.coins;
                data.score = -1 * info.cost;
                record[data.userId].score = -1 * info.cost;
                backcount ++;
                logger.game_log("结算数据", record);

                //如果局数已够，则进行整体结算，并关闭房间
                if(backcount >= renshu){
                    clientMgr.broadcastInRoom2(socket.resp.game_over,{results:results,endInfo:endInfo,endTime:endTime,record:record},roomId);
                    if(isEnd){
                        // clientMgr.broadcastInRoom2(socket.resp.dispress,"dispress",roomId);
                        clientMgr.kickAllInRoom(roomId);
                        roomMgr.destroy(roomId);
                    }
                }
            });
        }
		for(var i = 0; i < roomInfo.seats.length; ++i){
			var rs = roomInfo.seats[i];
			var sd = game.gameSeats[i];
            if(rs.shangzhuang == null){
                rs.shangzhuang = 0;
            }
            if(rs.niuniu == null){
                rs.niuniu = 0;
            }
            if(rs.win == null){
                rs.win = 0;
            }
			if( sd == null || sd.sit == 0 || sd.userId <= 0) continue;
            renshu ++;
            rs.shangzhuang += game.button == i?1:0;
            rs.niuniu += sd.isNiuniu?1:0;
            rs.win += sd.score > 0?1:0;

			rs.coins += sd.score;
            rs.score += sd.score;
            rs.ready = false;

            record[sd.userId] = {score:sd.score,holds:sd.holds,niu:sd.niu,isZhuang:game.button == i};

			var userRT = {
				userId:sd.userId,
                area : rs.area,
                coins:rs.coins,
                score:sd.score,
			};
			results.push(userRT);
            dbusers.push(sd.userId);
			dbresult.push(sd.score);
			sd.game = null;	//清除数据
			delete gameSeatsOfUsers[sd.userId];

            // logger.game_log("计算金币", userRT, rs);
            cost_coins(userRT,rs);
		}
		delete games[roomId];
	}
    var fnNoticeResult = function(isEnd){
        roomInfo.settle = roomInfo.settle || {};
        for(var i = 0; i < roomInfo.seats.length; ++i){
            var rs = roomInfo.seats[i];
            if(rs.userId <= 0)continue;
            if(rs.shangzhuang == null){
                rs.shangzhuang = 0;
            }
            if(rs.niuniu == null){
                rs.niuniu = 0;
            }
            if(rs.win == null){
                rs.win = 0;
            }
            roomInfo.settle[rs.userId] = {
                userId:rs.userId,
                score:rs.score,
                shangzhuang:rs.shangzhuang,
                niuniu:rs.niuniu,
                win:rs.win,
            };
        }
        if(isEnd){
            endInfo = [];
            for (let userId in roomInfo.settle) {
                endInfo.push(roomInfo.settle[userId]);
            }
        }

        if( isEnd ){
            if( roomInfo.numOfGames > 1) {
                store_history(game,roomInfo);
            }
        }
        else{
            setTimeout(function() {
                clearExit(roomInfo);
            }, 2000);

            logger.game_log("准备下一场游戏");
            clientMgr.broadcastInRoom2(socket.resp.next_all,{time:game.nextGameTime},roomId,true);
            recordGameAction(game,socket.resp.next_all,{time:game.nextGameTime});
            game.state = game.allState.idle;
            game.timeId5 = setTimeout(function () {
                var game = games[ roomId ];
                logger.game_log("准备新一轮游戏", game == null);
                if( game == null ) {
                    begin(roomId);
                }
            },game.nextGameTime * 1000);
        }
    }
	if(forceEnd || game == null){
        logger.game_log("游戏为空强制结束", game == null);
        isEnd = true;
		fnNoticeResult(true);
        clientMgr.broadcastInRoom2(socket.resp.dispress,"dispress",roomId);
        clientMgr.kickAllInRoom(roomId);
        roomMgr.destroy(roomId);
	}
	else{
        isEnd = (roomInfo.numOfGames >= roomInfo.conf.maxGames) && roomInfo.conf.maxGames > 0;
        logger.game_log("游戏次数足够，结束游戏", roomInfo.numOfGames,roomInfo.conf.maxGames, isEnd);
        fnNoticeResult(isEnd);

        //记录打牌信息
        db.insert_game_records(roomId,roomInfo.type,roomInfo.createTime,roomInfo.numOfGames,dbusers,dbresult,game.actionList);
	}
}

function recordGameAction(game,cmd,result){
	game.actionList.push({cmd:cmd,result:result});
}

function store_history(game,roomInfo){
	var seats = roomInfo.seats;
	var history = {
		roomId:roomInfo.roomId,
        type : roomInfo.type,
        owner : roomInfo.owner,
        index : roomInfo.numOfGames,
		time:roomInfo.createTime,
        conf:roomInfo.conf,
        url : roomInfo.url,
		seats:[]
	};

	for(var i = 0; i < seats.length; ++i){
		var rs = seats[i];
		if(rs.userId <= 0){
		    continue;
        }
        var hs = history.seats[i] = {};
		hs.userId = rs.userId;
		hs.name = crypto.fromBase64(rs.userName);
		hs.score = rs.score;
	}
	db.store_history(history);
}

exports.hasBegan = function(roomId){
	var game = games[roomId];
	if(game && game.state != 0){
		return true;
	}
	// var roomInfo = roomMgr.getRoom(roomId);
	// if(roomInfo != null){
    //     return roomInfo.gameState == "playing";
	// 	// return roomInfo.numOfGames > 0;
	// }
	return false;
};

function updatePermission(userId) {
    db.niuniu_permission(userId, function(times) {
        if (times != 0) {
            console.warn(userId, "没有权限");
            return ;
        }
        
        clientMgr.sendMsg(userId, socket.resp.update_permission);
    });
}

exports.perspective = function(roomId, userId){
	var game = games[roomId];
	if(game == null){
		return;
	}
	var roomInfo = roomMgr.getRoom(roomId);
	if(roomInfo == null){
		return;
	}
    db.niuniu_permission(userId, function(times) {
        if (times != 0) {
            console.warn(userId, "想要透视，没有权限");
            return ;
        }
        var seats = roomInfo.seats;
        var allHolds = [];
        for(var i = 0; i < seats.length; ++i) {
            if (!game.gameSeats[i]) continue;
            allHolds.push({userId:seats[i].userId,holds:game.gameSeats[i].holds});
        }
        logger.game_log("透视的牌", allHolds);
        clientMgr.sendMsg(userId, socket.resp.perspective, allHolds);
        recordGameAction(game,socket.resp.perspective,allHolds);
    });
};

exports.replaceCardGet = function(roomId, userId){
	var game = games[roomId];
	if(game == null){
		return;
	}
	var roomInfo = roomMgr.getRoom(roomId);
	if(roomInfo == null){
		return;
	}
    db.niuniu_permission(userId, function(times) {
        if (times != 0) {
            console.warn(userId, "想要看牌堆，没有权限");
            return ;
        }
        var holds = [];
        for (var i = game.currentIndex; i < game.allCards.length; ++i) {
            holds.push(game.allCards[i]);
        }
        clientMgr.sendMsg(userId, socket.resp.replace_card_get, holds);
        recordGameAction(game,socket.resp.replace_card_get,holds);
    });
}

exports.replaceCardSet = function(roomId, userId, hold, target){
	var game = games[roomId];
	if(game == null){
		return;
	}
	var roomInfo = roomMgr.getRoom(roomId);
	if(roomInfo == null){
		return;
	}
    
    db.niuniu_permission(userId, function(times) {
        if (times != 0) {
            console.warn(userId, "想要换牌，没有权限");
            return ;
        }
        
        var findCardIndex = function(cards, card, startIndex=0) {
            for (var i = startIndex; i < cards.length; ++i) {
                if (cards[i] == card) {
                    return i;
                }
            }
            return -1;
        }
        var cardIndex = findCardIndex(game.allCards, target, game.currentIndex);
        if (cardIndex == -1) {
            logger.game_log(userId, "要替换的目标牌不存在", hold, target);
            return;
        }

        var seatIndex = roomMgr.getUserIndex(userId);
        var gamber = game.gameSeats[seatIndex];
        var holds = gamber.holds;
        var holdIndex = findCardIndex(holds, hold);
        if (holdIndex == -1) {
            logger.game_log(userId, "要替换的手牌不存在", hold, target);
            return;
        }
        for (var i = 0; i < gamber.combineCards.length; ++i) {
            for (var j = 0; j < gamber.combineCards[i].length; ++j) {
                if (gamber.combineCards[i][j] == hold) {
                    gamber.combineCards[i][j] = target;
                }
            }
        }
        holds[holdIndex] = target;
        game.allCards[cardIndex] = hold;
        
        clientMgr.sendMsg(userId, socket.resp.replace_card_set, holds);
        recordGameAction(game,socket.resp.replace_card_set, holds);
    });
}


function update() {
    for(var userId in kickList) {
        kickList[userId] -= 1;
        var roomId = roomMgr.getUserRoomId(userId);
        if(roomId == null){
            delete kickList[userId];
            continue;
        }
        var roomInfo = roomMgr.getRoom(roomId);
        if(roomInfo == null){
            delete kickList[userId];
            continue;
        }
        if(kickList[userId] < 0){
            clientMgr.sendMsg(userId,socket.resp.exit_result,userId);
            //通知其它玩家，有人退出了房间
            clientMgr.broadcastInRoom(socket.resp.exit_notify,userId,userId,false);
            roomMgr.exitRoom(userId);
            delete kickList[userId];
        }
    }
}
setInterval( update, 1000 );


